﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using HtmlAgilityPack;

class Program
{
    static HttpClient client = new HttpClient();
    static ConcurrentDictionary<string, HashSet<string>> phoneNumbers = new ConcurrentDictionary<string, HashSet<string>>();
    static SemaphoreSlim semaphore = new SemaphoreSlim(10); 

    static async Task Main(string[] args)
    {
        Console.WriteLine("Enter keyword for search:");
        string keyword = Console.ReadLine();
        string googleSearchUrl = $"https://www.google.com/search?q={keyword} site:edu";

        client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");

        var html = await client.GetStringAsync(googleSearchUrl);
        var doc = new HtmlDocument();
        doc.LoadHtml(html);

        var nodes = doc.DocumentNode.SelectNodes("//a[@href]");
        if (nodes != null)
        {
            List<string> urls = nodes.Select(node =>
            {
                string href = node.GetAttributeValue("href", null);
                if (!string.IsNullOrEmpty(href))
                {
                    href = href.StartsWith("/url?q=") ? href.Substring(7, href.IndexOf('&') - 7) : href;
                    href = HttpUtility.UrlDecode(href);

                    if (Uri.TryCreate(href, UriKind.Absolute, out Uri validUri))
                    {
                        return validUri.ToString();
                    }
                }
                return null;
            })
            .Where(href => href != null)
            .Distinct()
            .ToList();

            var tasks = urls.Take(100).Select(url => ExtractPhoneNumbers(url)).ToArray();
            await Task.WhenAll(tasks);
        }

        if (phoneNumbers.Count > 0)
        {
            foreach (var kvp in phoneNumbers.Take(100))
            {
                Console.WriteLine($"Phone Number: {kvp.Key} found in URLs:");
                foreach (var url in kvp.Value)
                {
                    Console.WriteLine($"  - {url}");
                }
            }
        }
        else
        {
            Console.WriteLine("No phone numbers found.");
        }
    }

    static async Task ExtractPhoneNumbers(string url)
    {
        await semaphore.WaitAsync();
        try
        {
            var response = await client.GetAsync(url);
            if (response.IsSuccessStatusCode)
            {
                var html = await response.Content.ReadAsStringAsync();
                var doc = new HtmlDocument();
                doc.LoadHtml(html);

                var phoneNumberRegex = new Regex(@"\b\d{3}[-. ]?\d{3}[-. ]?\d{4}\b");
                var matches = phoneNumberRegex.Matches(html);

                foreach (Match match in matches)
                {
                    if (phoneNumbers.Count >= 100) break;

                    phoneNumbers.AddOrUpdate(match.Value, new HashSet<string> { url }, (key, oldValue) => { oldValue.Add(url); return oldValue; });
                }
            }
        }
        finally
        {
            semaphore.Release();
        }
    }
}
